from flask import Blueprint, request, jsonify
import jwt
import time
import json
import logging
from datetime import datetime
from decimal import Decimal
from ..config import Config
from ..extensions import redis_conn
from ..utils import device_required, process_music_styles, validate_user_id
from ..database import db_connection, mongo_collection
from ..models import db, Device, User, Song, Artist

device_bp = Blueprint('device', __name__)
logger = logging.getLogger('Device')
current_timestamp = int(time.time())

# 设备状态常量
DEVICE_STATUS = {
    'ACTIVATED': '激活',
    'INACTIVATED': '未激活',
    'ONLINE': '在线',
    'OFFLINE': '离线'
}

# 添加一个辅助函数来处理Decimal类型
def convert_decimal(obj):
    """将对象中的所有Decimal类型转换为float"""
    if isinstance(obj, dict):
        return {k: convert_decimal(v) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [convert_decimal(item) for item in obj]
    elif isinstance(obj, Decimal):
        return float(obj)
    else:
        return obj

@device_bp.route('/v1/data', methods=['POST'])
@device_required
def receive_data(device_id):
    try:
        if not request.is_json:
            return jsonify(Config.ERROR_CODES['INVALID_JSON']), 400
        
        data = request.get_json()
        required_fields = ['device_id', 'user_id', 'timestamp', 'song_id']
        if missing := [f for f in required_fields if f not in data]:
            return jsonify(code=40002, message=f"Missing fields: {', '.join(missing)}"), 400

        if data['device_id'] != device_id:
            return jsonify(Config.ERROR_CODES['DEVICE_MISMATCH']), 401

        try:
            # 验证用户和设备关系
            device = Device.query.get(device_id)
            if not device or str(device.user_id) != str(data['user_id']):
                return jsonify(code=40301, message="Unauthorized operation"), 403
            
            # 使用设备上传的时间戳
            timestamp = int(data['timestamp'])
            record_date = datetime.fromtimestamp(timestamp)
            
            # 使用设备上传的时间作为实际记录时间，而不是服务器时间
            date_str = record_date.strftime('%Y-%m-%d')
            month = record_date.strftime('%Y-%m')
            year = record_date.strftime('%Y')
            
            # 从MySQL获取歌曲信息
            song = Song.query.get(data['song_id'])
            if not song:
                return jsonify(code=40404, message="Song not found"), 404
            
            # 获取时段基于设备上传的时间戳
            hour = record_date.hour
            if 5 <= hour < 12:
                period = "morning"
            elif 12 <= hour < 18:
                period = "afternoon"
            elif 18 <= hour < 22:
                period = "evening"
            else:
                period = "night"
            
            # 获取更详细的时段（按小时）
            hour_period = f"hour_{hour}"
            
            song_duration = int(song.song_duration) if isinstance(song.song_duration, Decimal) else song.song_duration
            
            # 准备时段数据
            period_data = {period: song.song_duration}
            
            # 准备MongoDB文档 - 用户播放记录
            listen_record = {
                "device_id": device_id,
                "user_id": data['user_id'],
                "date": date_str,
                "timestamp": record_date,  # 使用设备上传的时间戳
                "song_id": data['song_id'],
                "song_name": song.song_name,
                "duration": song_duration,
                "period": period
            }
            
            # 在存储到MongoDB前转换所有数据
            listen_record = convert_decimal(listen_record)
            
            # 存储到MongoDB - 用户播放记录
            with mongo_collection(Config.MONGODB_COLLECTIONS["listen_records"]) as collection:
                collection.insert_one(listen_record)
            
            # 更新日偏好统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["daily_preferences"]) as collection:
                # 查找当天记录
                daily_record = collection.find_one({
                    "device_id": device_id,
                    "user_id": data['user_id'],
                    "date": date_str
                })
                
                if daily_record:
                    # 更新现有记录
                    period_prefs = daily_record.get("period_preferences", {})
                    
                    # 合并时段偏好
                    for p, minutes in period_data.items():
                        # 确保转换为float类型再相加
                        minutes_float = float(minutes) if isinstance(minutes, Decimal) else minutes
                        current_value = period_prefs.get(p, 0)
                        current_value_float = float(current_value) if isinstance(current_value, Decimal) else current_value
                        period_prefs[p] = current_value_float + minutes_float
                    
                    # 更新总时长 - 确保转换为float类型
                    total_duration = daily_record.get("total_duration", 0)
                    total_duration_float = float(total_duration) if isinstance(total_duration, Decimal) else total_duration
                    song_duration_float = float(song_duration) if isinstance(song_duration, Decimal) else song_duration
                    
                    # 更新记录 - 确保转换Decimal类型
                    update_data = {
                        "period_preferences": period_prefs,
                        "total_duration": total_duration_float + song_duration_float,
                        "updated_at": datetime.now()
                    }
                    update_data = convert_decimal(update_data)
                    
                    collection.update_one(
                        {"_id": daily_record["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录 - 确保转换Decimal类型
                    new_record = {
                        "device_id": device_id,
                        "user_id": data['user_id'],
                        "date": date_str,
                        "period_preferences": period_data,
                        "total_duration": song_duration,
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 同样更新月度和年度统计
            # 提取月份和年份 - 使用设备上传的时间
            # 注意：这里已经在前面定义了month和year变量
            
            # 更新月度统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["monthly_preferences"]) as collection:
                # 类似日统计的逻辑，但使用月份作为标识
                monthly_record = collection.find_one({
                    "device_id": device_id,
                    "user_id": data['user_id'],
                    "month": month
                })
                
                # 更新逻辑与日统计类似
                if monthly_record:
                    # 更新现有记录
                    period_prefs = monthly_record.get("period_preferences", {})
                    
                    for p, minutes in period_data.items():
                        # 确保转换为float类型再相加
                        minutes_float = float(minutes) if isinstance(minutes, Decimal) else minutes
                        current_value = period_prefs.get(p, 0)
                        current_value_float = float(current_value) if isinstance(current_value, Decimal) else current_value
                        period_prefs[p] = current_value_float + minutes_float
                    
                    # 更新总时长 - 确保转换为float类型
                    total_duration = monthly_record.get("total_duration", 0)
                    total_duration_float = float(total_duration) if isinstance(total_duration, Decimal) else total_duration
                    song_duration_float = float(song_duration) if isinstance(song_duration, Decimal) else song_duration
                    
                    # 更新记录 - 确保转换Decimal类型
                    update_data = {
                        "period_preferences": period_prefs,
                        "total_duration": total_duration_float + song_duration_float,
                        "updated_at": datetime.now()
                    }
                    update_data = convert_decimal(update_data)
                    
                    collection.update_one(
                        {"_id": monthly_record["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录 - 确保转换Decimal类型
                    new_record = {
                        "device_id": device_id,
                        "user_id": data['user_id'],
                        "month": month,
                        "period_preferences": period_data,
                        "total_duration": song_duration,
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 更新年度统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["yearly_preferences"]) as collection:
                # 类似月统计的逻辑，但使用年份作为标识
                yearly_record = collection.find_one({
                    "device_id": device_id,
                    "user_id": data['user_id'],
                    "year": year
                })
                
                if yearly_record:
                    # 更新现有记录
                    period_prefs = yearly_record.get("period_preferences", {})
                    
                    for p, minutes in period_data.items():
                        # 确保转换为float类型再相加
                        minutes_float = float(minutes) if isinstance(minutes, Decimal) else minutes
                        current_value = period_prefs.get(p, 0)
                        current_value_float = float(current_value) if isinstance(current_value, Decimal) else current_value
                        period_prefs[p] = current_value_float + minutes_float
                    
                    # 更新总时长 - 确保转换为float类型
                    total_duration = yearly_record.get("total_duration", 0)
                    total_duration_float = float(total_duration) if isinstance(total_duration, Decimal) else total_duration
                    song_duration_float = float(song_duration) if isinstance(song_duration, Decimal) else song_duration
                    
                    # 更新记录 - 确保转换Decimal类型
                    update_data = {
                        "period_preferences": period_prefs,
                        "total_duration": total_duration_float + song_duration_float,
                        "updated_at": datetime.now()
                    }
                    update_data = convert_decimal(update_data)
                    
                    collection.update_one(
                        {"_id": yearly_record["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录 - 确保转换Decimal类型
                    new_record = {
                        "device_id": device_id,
                        "user_id": data['user_id'],
                        "year": year,
                        "period_preferences": period_data,
                        "total_duration": song_duration,
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 新增代码：更新用户听歌时段频次统计 - 日统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["daily_duration"]) as collection:
                # 查找当天记录
                daily_duration = collection.find_one({
                    "user_id": data['user_id'],
                    "date": date_str
                })
                
                # 确保song_duration是float类型
                song_duration_float = float(song_duration) if isinstance(song_duration, Decimal) else song_duration
                
                if daily_duration:
                    # 更新现有记录
                    current_duration = daily_duration.get("duration", 0)
                    current_duration_float = float(current_duration) if isinstance(current_duration, Decimal) else current_duration
                    
                    # 获取时段频次数据
                    period_counts = daily_duration.get("period_counts", {})
                    period_counts[period] = period_counts.get(period, 0) + 1
                    
                    # 更新记录
                    update_data = {
                        "duration": current_duration_float + song_duration_float,
                        "listen_count": daily_duration.get("listen_count", 0) + 1,
                        "period_counts": period_counts,  # 添加时段频次统计
                        "updated_at": datetime.now()
                    }
                    update_data = convert_decimal(update_data)
                    
                    collection.update_one(
                        {"_id": daily_duration["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录
                    new_record = {
                        "user_id": data['user_id'],
                        "date": date_str,
                        "duration": song_duration_float,
                        "listen_count": 1,
                        "period_counts": {period: 1},
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 更新用户听歌时段频次统计 - 月统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["monthly_duration"]) as collection:
                # 查找当月记录
                monthly_duration = collection.find_one({
                    "user_id": data['user_id'],
                    "month": month
                })
                
                if monthly_duration:
                    # 更新现有记录
                    current_duration = monthly_duration.get("duration", 0)
                    current_duration_float = float(current_duration) if isinstance(current_duration, Decimal) else current_duration
                    
                    # 获取时段频次数据
                    period_counts = monthly_duration.get("period_counts", {})
                    period_counts[period] = period_counts.get(period, 0) + 1
                    
                    # 更新记录
                    update_data = {
                        "duration": current_duration_float + song_duration_float,
                        "listen_count": monthly_duration.get("listen_count", 0) + 1,
                        "period_counts": period_counts,
                        "updated_at": datetime.now()
                    }
                    update_data = convert_decimal(update_data)
                    
                    collection.update_one(
                        {"_id": monthly_duration["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录
                    new_record = {
                        "user_id": data['user_id'],
                        "month": month,
                        "duration": song_duration_float,
                        "listen_count": 1,
                        "period_counts": {period: 1},
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 更新用户听歌时段频次统计 - 年统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["yearly_duration"]) as collection:
                # 查找当年记录
                yearly_duration = collection.find_one({
                    "user_id": data['user_id'],
                    "year": year
                })
                
                if yearly_duration:
                    # 更新现有记录
                    current_duration = yearly_duration.get("duration", 0)
                    current_duration_float = float(current_duration) if isinstance(current_duration, Decimal) else current_duration
                    
                    # 获取时段频次数据
                    period_counts = yearly_duration.get("period_counts", {})
                    period_counts[period] = period_counts.get(period, 0) + 1
                    
                    # 更新记录
                    update_data = {
                        "duration": current_duration_float + song_duration_float,
                        "listen_count": yearly_duration.get("listen_count", 0) + 1,
                        "period_counts": period_counts,
                        "updated_at": datetime.now()
                    }
                    update_data = convert_decimal(update_data)
                    
                    collection.update_one(
                        {"_id": yearly_duration["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录
                    new_record = {
                        "user_id": data['user_id'],
                        "year": year,
                        "duration": song_duration_float,
                        "listen_count": 1,
                        "period_counts": {period: 1},
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 更新日度时段频次统计
            try:
                with mongo_collection(Config.MONGODB_COLLECTIONS["daily_period_stats"]) as collection:
                    # 查找当天记录
                    daily_period = collection.find_one({
                        "user_id": data['user_id'],
                        "date": date_str
                    })
                    
                    if daily_period:
                        # 更新现有记录
                        # 更新主要时段统计
                        period_counts = daily_period.get("period_counts", {})
                        period_counts[period] = period_counts.get(period, 0) + 1
                        
                        # 更新小时级别时段统计
                        hour_counts = daily_period.get("hour_counts", {})
                        hour_counts[hour_period] = hour_counts.get(hour_period, 0) + 1
                        
                        # 更新具体小时统计
                        exact_hour_counts = daily_period.get("exact_hour_counts", {})
                        exact_hour_counts[str(hour)] = exact_hour_counts.get(str(hour), 0) + 1
                        
                        # 更新记录
                        update_data = {
                            "period_counts": period_counts,
                            "hour_counts": hour_counts,
                            "exact_hour_counts": exact_hour_counts,
                            "total_count": daily_period.get("total_count", 0) + 1,
                            "updated_at": datetime.now()
                        }
                        
                        collection.update_one(
                            {"_id": daily_period["_id"]},
                            {"$set": update_data}
                        )
                    else:
                        # 创建新记录
                        new_record = {
                            "user_id": data['user_id'],
                            "date": date_str,
                            "period_counts": {period: 1},
                            "hour_counts": {hour_period: 1},
                            "exact_hour_counts": {str(hour): 1},
                            "total_count": 1,
                            "created_at": datetime.now(),
                            "updated_at": datetime.now()
                        }
                        new_record = convert_decimal(new_record)
                        collection.insert_one(new_record)
            except Exception as e:
                logger.error(f"更新日度时段频次统计失败: {str(e)}")
                # 继续执行，不中断流程
            
            # 更新月度时段频次统计
            try:
                with mongo_collection(Config.MONGODB_COLLECTIONS["monthly_period_stats"]) as collection:
                    # 查找当月记录
                    monthly_period = collection.find_one({
                        "user_id": data['user_id'],
                        "month": month
                    })
                    
                    if monthly_period:
                        # 更新现有记录
                        # 更新主要时段统计
                        period_counts = monthly_period.get("period_counts", {})
                        period_counts[period] = period_counts.get(period, 0) + 1
                        
                        # 更新小时级别时段统计
                        hour_counts = monthly_period.get("hour_counts", {})
                        hour_counts[hour_period] = hour_counts.get(hour_period, 0) + 1
                        
                        # 更新具体小时统计
                        exact_hour_counts = monthly_period.get("exact_hour_counts", {})
                        exact_hour_counts[str(hour)] = exact_hour_counts.get(str(hour), 0) + 1
                        
                        # 更新星期几统计
                        weekday = record_date.weekday()  # 0-6 表示周一到周日
                        weekday_counts = monthly_period.get("weekday_counts", {})
                        weekday_counts[str(weekday)] = weekday_counts.get(str(weekday), 0) + 1
                        
                        # 更新记录
                        update_data = {
                            "period_counts": period_counts,
                            "hour_counts": hour_counts,
                            "exact_hour_counts": exact_hour_counts,
                            "weekday_counts": weekday_counts,
                            "total_count": monthly_period.get("total_count", 0) + 1,
                            "updated_at": datetime.now()
                        }
                        update_data = convert_decimal(update_data)
                        
                        collection.update_one(
                            {"_id": monthly_period["_id"]},
                            {"$set": update_data}
                        )
                    else:
                        # 创建新记录
                        weekday = record_date.weekday()
                        new_record = {
                            "user_id": data['user_id'],
                            "month": month,
                            "period_counts": {period: 1},
                            "hour_counts": {hour_period: 1},
                            "exact_hour_counts": {str(hour): 1},
                            "weekday_counts": {str(weekday): 1},
                            "total_count": 1,
                            "created_at": datetime.now(),
                            "updated_at": datetime.now()
                        }
                        new_record = convert_decimal(new_record)
                        collection.insert_one(new_record)
            except Exception as e:
                logger.error(f"更新月度时段频次统计失败: {str(e)}")
                # 继续执行，不中断流程
            
            # 更新年度时段频次统计
            try:
                with mongo_collection(Config.MONGODB_COLLECTIONS["yearly_period_stats"]) as collection:
                    # 查找当年记录
                    yearly_period = collection.find_one({
                        "user_id": data['user_id'],
                        "year": year
                    })
                    
                    if yearly_period:
                        # 更新现有记录
                        # 更新主要时段统计
                        period_counts = yearly_period.get("period_counts", {})
                        period_counts[period] = period_counts.get(period, 0) + 1
                        
                        # 更新小时级别时段统计
                        hour_counts = yearly_period.get("hour_counts", {})
                        hour_counts[hour_period] = hour_counts.get(hour_period, 0) + 1
                        
                        # 更新具体小时统计
                        exact_hour_counts = yearly_period.get("exact_hour_counts", {})
                        exact_hour_counts[str(hour)] = exact_hour_counts.get(str(hour), 0) + 1
                        
                        # 更新星期几统计
                        weekday = record_date.weekday()
                        weekday_counts = yearly_period.get("weekday_counts", {})
                        weekday_counts[str(weekday)] = weekday_counts.get(str(weekday), 0) + 1
                        
                        # 更新月份统计
                        month_num = record_date.month  # 1-12
                        month_counts = yearly_period.get("month_counts", {})
                        month_counts[str(month_num)] = month_counts.get(str(month_num), 0) + 1
                        
                        # 更新记录
                        update_data = {
                            "period_counts": period_counts,
                            "hour_counts": hour_counts,
                            "exact_hour_counts": exact_hour_counts,
                            "weekday_counts": weekday_counts,
                            "month_counts": month_counts,
                            "total_count": yearly_period.get("total_count", 0) + 1,
                            "updated_at": datetime.now()
                        }
                        update_data = convert_decimal(update_data)
                        
                        collection.update_one(
                            {"_id": yearly_period["_id"]},
                            {"$set": update_data}
                        )
                    else:
                        # 创建新记录
                        weekday = record_date.weekday()
                        month_num = record_date.month
                        new_record = {
                            "user_id": data['user_id'],
                            "year": year,
                            "period_counts": {period: 1},
                            "hour_counts": {hour_period: 1},
                            "exact_hour_counts": {str(hour): 1},
                            "weekday_counts": {str(weekday): 1},
                            "month_counts": {str(month_num): 1},
                            "total_count": 1,
                            "created_at": datetime.now(),
                            "updated_at": datetime.now()
                        }
                        new_record = convert_decimal(new_record)
                        collection.insert_one(new_record)
            except Exception as e:
                logger.error(f"更新年度时段频次统计失败: {str(e)}")
                # 继续执行，不中断流程
            
            logger.info(f"数据已存入MongoDB: device_id={device_id}, song_id={data['song_id']}")
            return jsonify(code=0, message="Listen record processed successfully"), 200
            
        except Exception as e:
            logger.error(f"数据库操作失败: {str(e)}")
            return jsonify(code=50001, message=str(e)), 500

    except Exception as e:
        logger.exception("接收数据异常")
        return jsonify(code=50000, message="Internal server error"), 500

@device_bp.route('/v2/data', methods=['POST'])
def receive_data_v2():
    try:
        if not request.is_json:
            return jsonify(Config.ERROR_CODES['INVALID_JSON']), 400
        
        data = request.get_json()
        required_fields = ['device_id', 'user_id', 'timestamp', 'song_name', 'id', 'artists', 'dt']
        if missing := [f for f in required_fields if f not in data]:
            return jsonify(code=40002, message=f"Missing fields: {', '.join(missing)}"), 400

        device_id = data['device_id']
        
        try:
            # 验证用户和设备关系
            device = Device.query.get(device_id)
            if not device or str(device.user_id) != str(data['user_id']):
                return jsonify(code=40301, message="Unauthorized operation"), 403
            
            # 检查歌曲是否存在于MySQL数据库，不存在则创建
            song = Song.query.filter_by(song_id=str(data['id'])).first()
            if not song:
                # 创建新歌曲记录
                song = Song(
                    song_id=str(data['id']),
                    song_name=data['song_name'],
                    song_duration=data['dt'] / 1000  # 毫秒转换为秒
                )
                db.session.add(song)
                
                # 处理艺术家关联
                for artist_data in data['artists']:
                    # 检查艺术家是否已存在
                    artist = Artist.query.filter_by(artist_name=artist_data.get('name')).first()
                    if not artist:
                        # 创建新艺术家
                        artist = Artist(artist_name=artist_data.get('name'))
                        db.session.add(artist)
                        db.session.flush()  # 获取自动生成的ID
                    
                    # 创建艺术家与歌曲的关联
                    if artist not in song.artists:
                        song.artists.append(artist)
                
                db.session.commit()
                logger.info(f"创建新歌曲: {song.song_name} (ID: {song.song_id})")
            
            # 使用设备上传的时间戳
            timestamp = int(data['timestamp'] / 1000)
            record_date = datetime.fromtimestamp(timestamp)
            
            # 使用设备上传的时间作为实际记录时间，而不是服务器时间
            date_str = record_date.strftime('%Y-%m-%d')
            month = record_date.strftime('%Y-%m')
            year = record_date.strftime('%Y')
            
            # 获取歌曲时长（毫秒转换为秒）
            song_duration = data['dt'] / 1000  # 毫秒转换为秒
            
            # 获取时段基于设备上传的时间戳
            hour = record_date.hour
            if 5 <= hour < 12:
                period = "morning"
            elif 12 <= hour < 18:
                period = "afternoon"
            elif 18 <= hour < 22:
                period = "evening"
            else:
                period = "night"
            
            # 获取更详细的时段（按小时）
            hour_period = f"hour_{hour}"
            
            # 准备时段数据
            period_data = {period: song_duration}
            
            # 准备艺术家信息
            artists = []
            for artist in data['artists']:
                artists.append({
                    "id": artist.get('id'),
                    "name": artist.get('name')
                })
            
            # 准备MongoDB文档 - 用户播放记录
            listen_record = {
                "device_id": device_id,
                "user_id": data['user_id'],
                "date": date_str,
                "timestamp": record_date,  # 使用设备上传的时间戳
                "song_id": data['id'],
                "song_name": data['song_name'],
                "duration": song_duration,
                "period": period,
                "artists": artists
            }
            
            # 在存储到MongoDB前转换所有数据，确保没有Decimal类型
            listen_record = convert_decimal(listen_record)
            
            # 存储到MongoDB - 用户播放记录
            with mongo_collection(Config.MONGODB_COLLECTIONS["listen_records"]) as collection:
                collection.insert_one(listen_record)
            
            # 更新日偏好统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["daily_preferences"]) as collection:
                # 查找当天记录
                daily_record = collection.find_one({
                    "device_id": device_id,
                    "user_id": data['user_id'],
                    "date": date_str
                })
                
                if daily_record:
                    # 更新现有记录
                    period_prefs = daily_record.get("period_preferences", {})
                    
                    # 合并时段偏好
                    for p, minutes in period_data.items():
                        # 确保转换为float类型再相加
                        minutes_float = float(minutes) if isinstance(minutes, Decimal) else minutes
                        current_value = period_prefs.get(p, 0)
                        current_value_float = float(current_value) if isinstance(current_value, Decimal) else current_value
                        period_prefs[p] = current_value_float + minutes_float
                    
                    # 更新总时长 - 确保转换为float类型
                    total_duration = daily_record.get("total_duration", 0)
                    total_duration_float = float(total_duration) if isinstance(total_duration, Decimal) else total_duration
                    song_duration_float = float(song_duration) if isinstance(song_duration, Decimal) else song_duration
                    
                    # 更新记录 - 确保转换Decimal类型
                    update_data = {
                        "period_preferences": period_prefs,
                        "total_duration": total_duration_float + song_duration_float,
                        "updated_at": datetime.now()
                    }
                    update_data = convert_decimal(update_data)
                    
                    collection.update_one(
                        {"_id": daily_record["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录 - 确保转换Decimal类型
                    new_record = {
                        "device_id": device_id,
                        "user_id": data['user_id'],
                        "date": date_str,
                        "period_preferences": period_data,
                        "total_duration": song_duration,
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 更新月度偏好统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["monthly_preferences"]) as collection:
                # 查找当月记录
                monthly_record = collection.find_one({
                    "device_id": device_id,
                    "user_id": data['user_id'],
                    "month": month
                })
                
                if monthly_record:
                    # 更新现有记录
                    period_prefs = monthly_record.get("period_preferences", {})
                    
                    # 合并时段偏好
                    for p, minutes in period_data.items():
                        # 确保转换为float类型再相加
                        minutes_float = float(minutes) if isinstance(minutes, Decimal) else minutes
                        current_value = period_prefs.get(p, 0)
                        current_value_float = float(current_value) if isinstance(current_value, Decimal) else current_value
                        period_prefs[p] = current_value_float + minutes_float
                    
                    # 更新总时长 - 确保转换为float类型
                    total_duration = monthly_record.get("total_duration", 0)
                    total_duration_float = float(total_duration) if isinstance(total_duration, Decimal) else total_duration
                    song_duration_float = float(song_duration) if isinstance(song_duration, Decimal) else song_duration
                    
                    # 更新记录 - 确保转换Decimal类型
                    update_data = {
                        "period_preferences": period_prefs,
                        "total_duration": total_duration_float + song_duration_float,
                        "updated_at": datetime.now()
                    }
                    update_data = convert_decimal(update_data)
                    
                    collection.update_one(
                        {"_id": monthly_record["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录 - 确保转换Decimal类型
                    new_record = {
                        "device_id": device_id,
                        "user_id": data['user_id'],
                        "month": month,
                        "period_preferences": period_data,
                        "total_duration": song_duration,
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 更新年度偏好统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["yearly_preferences"]) as collection:
                # 查找当年记录
                yearly_record = collection.find_one({
                    "device_id": device_id,
                    "user_id": data['user_id'],
                    "year": year
                })
                
                if yearly_record:
                    # 更新现有记录
                    period_prefs = yearly_record.get("period_preferences", {})
                    
                    # 合并时段偏好
                    for p, minutes in period_data.items():
                        # 确保转换为float类型再相加
                        minutes_float = float(minutes) if isinstance(minutes, Decimal) else minutes
                        current_value = period_prefs.get(p, 0)
                        current_value_float = float(current_value) if isinstance(current_value, Decimal) else current_value
                        period_prefs[p] = current_value_float + minutes_float
                    
                    # 更新总时长 - 确保转换为float类型
                    total_duration = yearly_record.get("total_duration", 0)
                    total_duration_float = float(total_duration) if isinstance(total_duration, Decimal) else total_duration
                    song_duration_float = float(song_duration) if isinstance(song_duration, Decimal) else song_duration
                    
                    # 更新记录 - 确保转换Decimal类型
                    update_data = {
                        "period_preferences": period_prefs,
                        "total_duration": total_duration_float + song_duration_float,
                        "updated_at": datetime.now()
                    }
                    update_data = convert_decimal(update_data)
                    
                    collection.update_one(
                        {"_id": yearly_record["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录 - 确保转换Decimal类型
                    new_record = {
                        "device_id": device_id,
                        "user_id": data['user_id'],
                        "year": year,
                        "period_preferences": period_data,
                        "total_duration": song_duration,
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 更新用户听歌时段频次统计 - 日统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["daily_duration"]) as collection:
                # 查找当天记录
                daily_duration = collection.find_one({
                    "user_id": data['user_id'],
                    "date": date_str
                })
                
                if daily_duration:
                    # 更新现有记录
                    current_duration = daily_duration.get("duration", 0)
                    
                    # 获取时段频次数据
                    period_counts = daily_duration.get("period_counts", {})
                    period_counts[period] = period_counts.get(period, 0) + 1
                    
                    # 更新记录
                    update_data = {
                        "duration": current_duration + song_duration,
                        "listen_count": daily_duration.get("listen_count", 0) + 1,
                        "period_counts": period_counts,  # 添加时段频次统计
                        "updated_at": datetime.now()
                    }
                    
                    collection.update_one(
                        {"_id": daily_duration["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录
                    new_record = {
                        "user_id": data['user_id'],
                        "date": date_str,
                        "duration": song_duration,
                        "listen_count": 1,
                        "period_counts": {period: 1},
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 更新用户听歌时段频次统计 - 月统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["monthly_duration"]) as collection:
                # 查找当月记录
                monthly_duration = collection.find_one({
                    "user_id": data['user_id'],
                    "month": month
                })
                
                if monthly_duration:
                    # 更新现有记录
                    current_duration = monthly_duration.get("duration", 0)
                    
                    # 获取时段频次数据
                    period_counts = monthly_duration.get("period_counts", {})
                    period_counts[period] = period_counts.get(period, 0) + 1
                    
                    # 更新记录
                    update_data = {
                        "duration": current_duration + song_duration,
                        "listen_count": monthly_duration.get("listen_count", 0) + 1,
                        "period_counts": period_counts,
                        "updated_at": datetime.now()
                    }
                    
                    collection.update_one(
                        {"_id": monthly_duration["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录
                    new_record = {
                        "user_id": data['user_id'],
                        "month": month,
                        "duration": song_duration,
                        "listen_count": 1,
                        "period_counts": {period: 1},
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 更新用户听歌时段频次统计 - 年统计
            with mongo_collection(Config.MONGODB_COLLECTIONS["yearly_duration"]) as collection:
                # 查找当年记录
                yearly_duration = collection.find_one({
                    "user_id": data['user_id'],
                    "year": year
                })
                
                if yearly_duration:
                    # 更新现有记录
                    current_duration = yearly_duration.get("duration", 0)
                    
                    # 获取时段频次数据
                    period_counts = yearly_duration.get("period_counts", {})
                    period_counts[period] = period_counts.get(period, 0) + 1
                    
                    # 更新记录
                    update_data = {
                        "duration": current_duration + song_duration,
                        "listen_count": yearly_duration.get("listen_count", 0) + 1,
                        "period_counts": period_counts,
                        "updated_at": datetime.now()
                    }
                    
                    collection.update_one(
                        {"_id": yearly_duration["_id"]},
                        {"$set": update_data}
                    )
                else:
                    # 创建新记录
                    new_record = {
                        "user_id": data['user_id'],
                        "year": year,
                        "duration": song_duration,
                        "listen_count": 1,
                        "period_counts": {period: 1},
                        "created_at": datetime.now(),
                        "updated_at": datetime.now()
                    }
                    new_record = convert_decimal(new_record)
                    collection.insert_one(new_record)
            
            # 更新日度时段频次统计
            try:
                with mongo_collection(Config.MONGODB_COLLECTIONS["daily_period_stats"]) as collection:
                    # 查找当天记录
                    daily_period = collection.find_one({
                        "user_id": data['user_id'],
                        "date": date_str
                    })
                    
                    if daily_period:
                        # 更新现有记录
                        # 更新主要时段统计
                        period_counts = daily_period.get("period_counts", {})
                        period_counts[period] = period_counts.get(period, 0) + 1
                        
                        # 更新小时级别时段统计
                        hour_counts = daily_period.get("hour_counts", {})
                        hour_counts[hour_period] = hour_counts.get(hour_period, 0) + 1
                        
                        # 更新具体小时统计
                        exact_hour_counts = daily_period.get("exact_hour_counts", {})
                        exact_hour_counts[str(hour)] = exact_hour_counts.get(str(hour), 0) + 1
                        
                        # 更新记录
                        update_data = {
                            "period_counts": period_counts,
                            "hour_counts": hour_counts,
                            "exact_hour_counts": exact_hour_counts,
                            "total_count": daily_period.get("total_count", 0) + 1,
                            "updated_at": datetime.now()
                        }
                        
                        collection.update_one(
                            {"_id": daily_period["_id"]},
                            {"$set": update_data}
                        )
                    else:
                        # 创建新记录
                        new_record = {
                            "user_id": data['user_id'],
                            "date": date_str,
                            "period_counts": {period: 1},
                            "hour_counts": {hour_period: 1},
                            "exact_hour_counts": {str(hour): 1},
                            "total_count": 1,
                            "created_at": datetime.now(),
                            "updated_at": datetime.now()
                        }
                        new_record = convert_decimal(new_record)
                        collection.insert_one(new_record)
            except Exception as e:
                logger.error(f"更新日度时段频次统计失败: {str(e)}")
                # 继续执行，不中断流程
            
            logger.info(f"数据已存入MongoDB: device_id={device_id}, song_id={data['id']}")
            return jsonify(code=0, message="Listen record processed successfully"), 200
            
        except Exception as e:
            logger.error(f"数据库操作失败: {str(e)}")
            return jsonify(code=50001, message=str(e)), 500

    except Exception as e:
        logger.exception("接收数据异常")
        return jsonify(code=50000, message="Internal server error"), 500

# 上报设备状态
@device_bp.route('/v1/update_status', methods=['POST'])
@device_required
def report_status(device_id):
    """
    设备状态上报接口
    """
    try:
        # 请求验证
        if not request.is_json:
            return jsonify(Config.ERROR_CODES['INVALID_JSON']), 400
            
        data = request.get_json()
        required_fields = ['device_id', 'timestamp', 'Power', 'Net', 'Audio']
        if missing := [f for f in required_fields if f not in data]:
            return jsonify(
                code=Config.ERROR_CODES['MISSING_FIELD'][0],
                message=f"{Config.ERROR_CODES['MISSING_FIELD'][1]}: {', '.join(missing)}"
            ), 400

        timestamp = data['timestamp']

        # 验证代码...
        if not 0 <= data['Power']['battery_level'] <= 100:
            return jsonify(code=40011, message="电池电量无效"), 400

        if data['Net']['net_delay'] < 0:
            return jsonify(code=40012, message="网络延迟无效"), 400

        if data['Power']['isCharging'] not in ['Charging', 'Discharging', 'Full']:
            return jsonify(code=40013, message="充电状态无效"), 400

        # 设备ID验证
        if data['device_id'] != device_id:
            logger.warning(f"设备ID不匹配 请求:{data['device_id']} 实际:{device_id}")
            return jsonify(Config.ERROR_CODES['DEVICE_MISMATCH']), 403

        # 时间戳验证（±5分钟）
        try:
            # 将毫秒级时间戳转换为秒
            client_timestamp = int(timestamp) / 1000  
            current_timestamp = time.time()
            time_diff = abs(current_timestamp - client_timestamp)
            
            if time_diff > 300:
                logger.warning(f"过期时间戳: {timestamp} (转换后:{client_timestamp}), 当前时间戳: {current_timestamp}, 差: {time_diff}")
                return jsonify(
                    code=Config.ERROR_CODES['EXPIRED_TIMESTAMP'][0],
                    message=Config.ERROR_CODES['EXPIRED_TIMESTAMP'][1],
                    detail={
                        "client_timestamp": client_timestamp,
                        "server_timestamp": current_timestamp,
                        "time_diff_seconds": round(time_diff, 2),
                        "max_allowed_diff": 300
                    }
                ), 401
        except ValueError:
            logger.warning(f"非法时间戳格式: {timestamp}")
            return jsonify(
                code=40008,
                message="时间戳必须为13位毫秒级整数"
            ), 400

        # 验证设备存在于MySQL
        device = Device.query.get(device_id)
        if not device:
            return jsonify(code=40401, message="Device not found"), 404

        # 自动将设备激活状态设置为已激活
        if not device.is_activated:
            device.is_activated = True
            device.activation_time = datetime.now()
            db.session.commit()
            logger.info(f"设备自动激活: device_id={device_id}")

        # 确定设备状态
        connection_status = "ONLINE"  # 默认为在线
        
        # 根据电源状态判断连接状态
        if data['Power']['state'] == "OFF":
            connection_status = "OFFLINE"
        
        # 确定激活状态 - 从数据库获取 (此时已经是激活状态)
        activation_status = "ACTIVATED"
        
        # 准备MongoDB文档
        timestamp_dt = datetime.fromtimestamp(int(timestamp) / 1000)
        
        # 确保数值类型正确
        battery_level = int(data['Power']['battery_level']) if isinstance(data['Power']['battery_level'], (Decimal, str)) else data['Power']['battery_level']
        net_delay = int(data['Net']['net_delay']) if isinstance(data['Net']['net_delay'], (Decimal, str)) else data['Net']['net_delay']
        
        mongo_doc = {
            "device_id": device_id,
            "timestamp": timestamp_dt,
            "received_at": datetime.now(),
            "connection_status": connection_status,  # 连接状态：在线/离线
            "activation_status": activation_status,  # 激活状态：激活/未激活
            "power": {
                "state": data['Power']['state'],
                "battery_level": battery_level,
                "charging_state": data['Power']['isCharging']
            },
            "network": {
                "wifi_state": data['Net']['Wifi_state'],
                "net_delay": net_delay
            },
            "audio": {
                "effect": data['Audio']['effect'],
                "mode": data['Audio']['mode']
            }
        }
        
        # 存储到MongoDB
        with mongo_collection(Config.MONGODB_COLLECTIONS["device_status"]) as collection:
            collection.insert_one(mongo_doc)
            
        logger.info(f"设备状态已存入MongoDB: device_id={device_id}, connection_status={connection_status}, activation_status={activation_status}")

        return jsonify({
            "code": 0,
            "device_id": device_id,
            "connection_status": DEVICE_STATUS[connection_status],  # 返回中文状态
            "activation_status": DEVICE_STATUS[activation_status],  # 返回中文状态
            "received_at": datetime.utcnow().isoformat() + "Z"
        }), 200

    except Exception as e:
        logger.exception("状态上报流程异常")
        return jsonify(code=50000, message="系统繁忙，请稍后重试"), 500

# 新增设备注册接口
@device_bp.route('/v1/device_register', methods=['POST'])
def register_device():
    """
    设备注册接口
    请求示例：
    {
        "device_id": "CQUCHX0503001",
        "device_key": "device_secret_key_123"
    }
    """
    try:
        # 请求验证
        if not request.is_json:
            return jsonify(
                code=Config.ERROR_CODES['INVALID_JSON'][0], 
                message=Config.ERROR_CODES['INVALID_JSON'][1]
            ), 400
            
        data = request.get_json()
        required_fields = ['device_id', 'device_key']
        if missing := [f for f in required_fields if f not in data]:
            return jsonify(
                code=Config.ERROR_CODES['MISSING_FIELD'][0],
                message=f"{Config.ERROR_CODES['MISSING_FIELD'][1]}: {', '.join(missing)}"
            ), 400
        
        device_id = data['device_id']
        device_key = data['device_key']
        
        # 检查设备是否已存在
        existing_device = Device.query.get(device_id)
        if existing_device:
            return jsonify(code=40009, message="Device already registered"), 409
        
        # 注册新设备
        new_device = Device(
            device_id=device_id,
            device_key=device_key,
            create_at=datetime.now()
        )
        
        db.session.add(new_device)
        db.session.commit()
        
        return jsonify({
            "code": 0,
            "message": "Device registered successfully",
            "device_id": device_id
        }), 201
                
    except Exception as e:
        db.session.rollback()
        logger.exception(f"设备注册异常: {str(e)}")
        return jsonify(code=50000, message="Internal server error"), 500

# 新增设备激活接口
@device_bp.route('/v1/activate_device', methods=['POST'])
def activate_device():
    """
    设备激活接口
    请求示例：
    {
        "device_id": "CQUCHX0503001",
        "activation_code": "XXXX-XXXX-XXXX-XXXX"
    }
    """
    try:
        # 请求验证
        if not request.is_json:
            return jsonify(
                code=Config.ERROR_CODES['INVALID_JSON'][0], 
                message=Config.ERROR_CODES['INVALID_JSON'][1]
            ), 400
            
        data = request.get_json()
        required_fields = ['device_id', 'activation_code']
        if missing := [f for f in required_fields if f not in data]:
            return jsonify(
                code=Config.ERROR_CODES['MISSING_FIELD'][0],
                message=f"{Config.ERROR_CODES['MISSING_FIELD'][1]}: {', '.join(missing)}"
            ), 400
        
        device_id = data['device_id']
        activation_code = data['activation_code']
        
        # 检查设备是否存在
        device = Device.query.get(device_id)
        if not device:
            return jsonify(code=40401, message="设备不存在"), 404
        
        # 检查激活码是否正确（这里简化处理，实际应该有激活码验证逻辑）
        # 假设正确的激活码格式为：设备ID的前8位 + "-ACTIVE"
        expected_code = f"{device_id[:8]}-ACTIVE"
        
        if activation_code != expected_code:
            return jsonify(code=40014, message="激活码无效"), 400
        
        # 激活设备
        device.is_activated = True
        device.activation_time = datetime.now()
        db.session.commit()
        
        return jsonify({
            "code": 0,
            "message": "设备激活成功",
            "device_id": device_id,
            "status": DEVICE_STATUS['ACTIVATED']
        }), 200
                
    except Exception as e:
        db.session.rollback()
        logger.exception(f"设备激活异常: {str(e)}")
        return jsonify(code=50000, message="Internal server error"), 500

# 查询设备状态接口
@device_bp.route('/v1/device_status/<device_id>', methods=['GET'])
def get_device_status(device_id):
    """
    查询设备状态接口
    """
    try:
        # 验证设备是否存在
        device = Device.query.get(device_id)
        if not device:
            return jsonify(code=40401, message="设备不存在"), 404
        
        # 获取设备最新状态
        with mongo_collection(Config.MONGODB_COLLECTIONS["device_status"]) as collection:
            # 查找最新一条状态记录
            latest_status = collection.find_one(
                {"device_id": device_id},
                sort=[("timestamp", -1)]
            )
        
        if not latest_status:
            # 如果没有状态记录，则返回默认状态
            activation_status = "ACTIVATED" if device.is_activated else "INACTIVATED"
            return jsonify({
                "code": 0,
                "device_id": device_id,
                "connection_status": DEVICE_STATUS['OFFLINE'],  # 默认离线
                "activation_status": DEVICE_STATUS[activation_status],
                "last_online": None
            }), 200
        
        # 返回设备状态
        return jsonify({
            "code": 0,
            "device_id": device_id,
            "connection_status": DEVICE_STATUS[latest_status.get("connection_status", "OFFLINE")],
            "activation_status": DEVICE_STATUS[latest_status.get("activation_status", "INACTIVATED")],
            "last_online": latest_status.get("timestamp").isoformat() if latest_status.get("timestamp") else None,
            "battery_level": latest_status.get("power", {}).get("battery_level"),
            "charging_state": latest_status.get("power", {}).get("charging_state")
        }), 200
                
    except Exception as e:
        logger.exception(f"查询设备状态异常: {str(e)}")
        return jsonify(code=50000, message="Internal server error"), 500